package com.sense.kukoo.biz_explore.vm

import android.util.Log
import androidx.lifecycle.MutableLiveData
import com.sense.feel.common.utils.ToastUtils
import com.sense.kukoo.biz_explore.model.SearchModel
import com.sense.kukoo.common.mvvm.model.BaseMvvmModel
import com.sense.kukoo.common.mvvm.vm.BaseViewModel
import com.sense.kukoo.common.repo.Repo
import com.sense.kukoo.common.repo.bean.*
import com.sense.kukoo.common.repo.http.bean.IndexContentBean
import com.sense.kukoo.common.repo.http.bean.UserSearchBean
import com.sense.kukoo.lib_logger.LoggerManager

class SearchViewModel : BaseViewModel() {

    private val TAG: String = javaClass.simpleName
    private var mRecommend: SearchBean? = null
    private val mRecentTitle: SearchBean = SearchBean(SearchBean.TYPE_RECENT_TITLE, "title")
    private val mRecentItemList: ArrayList<SearchBean> = arrayListOf()
    private var mLastSearch: String? = null
    private var mLastSearchIsLoadMore: Boolean = false
    private var mIndex = 2
    private val mPageSize = 10

    val action_refreshPosition: MutableLiveData<Int> = MutableLiveData()
    val action_networkError: MutableLiveData<Boolean> = MutableLiveData()

    val mEnableLoadMore: MutableLiveData<Boolean> = MutableLiveData(false)
    val mEnableRefresh: MutableLiveData<Boolean> = MutableLiveData(false)

    val mHintList: MutableLiveData<MutableList<SearchBean>> = MutableLiveData(arrayListOf())
    val mSearchResultList: MutableLiveData<MutableList<SearchBean>> = MutableLiveData()

    override fun createModel(): BaseMvvmModel? = null

    override fun initData() {}

    //搜索前的提示（Recommend, Recent Search）
    fun getHintData() {
        request {
            //Recent Search
            refreshRecentItemList()
            showHintData()

            //Recommend
            val hotWordQueryPage = Repo.http.hotWordList()
            if (hotWordQueryPage.success) {
                val records:List<String> = hotWordQueryPage.data!!
                //
                val recommendKeywords = arrayListOf<String>()
                records.forEach {
                    recommendKeywords.add(it)
                }
                //
                mRecommend = SearchBean(
                        type = SearchBean.TYPE_RECOMMEND,
                        recommend = recommendKeywords
                )
                //
                showHintData()
            } else {
                Log.e(TAG, "result=" + hotWordQueryPage.msg)
            }
        }
    }

    private fun refreshRecentItemList() {
        mRecentItemList.clear()
        val searchHistory = Repo.searchHistory.getSearchHistory()
        searchHistory.forEach { text ->
            mRecentItemList.add(SearchBean(SearchBean.TYPE_RECENT_ITEM, text))
        }
    }

    fun showHintData() {
        val data: MutableList<SearchBean> = mHintList.value!!
        data.clear()
        //Recommend
        val recommendSize = mRecommend?.recommend?.size ?: 0
        if (recommendSize > 0) {
            data.add(mRecommend!!)
        }
        //Recent Search
        if (mRecentItemList.size > 0) {
            data.add(mRecentTitle)
            data.addAll(mRecentItemList)
        }
        mHintList.postValue(data)
        mEnableLoadMore.postValue(false)
        mEnableRefresh.postValue(false)
    }

    fun setCleanAll() {
        request {
            mRecentItemList.clear()
            Repo.searchHistory.deleteAllSearch()
            showHintData()
        }
    }

    fun setDeleteRecentSearch(bean: SearchBean) {
        request {
            mRecentItemList.remove(bean)
            Repo.searchHistory.deleteSearch(bean.keyword)
            showHintData()
        }
    }

    fun refreshSearch() {
        if (mLastSearchIsLoadMore) {
            getMoreSearchData()
        } else {
            mLastSearch?.let {
                getSearchData(it)
            }
        }
    }

    fun refreshSearchOnLogin(){
        mLastSearch?.let {
            getSearchData(it)
        }
    }

    fun getSearchData(text: String) {
        toView(ACTION_SHOW_DIALOG)
        val onError: (error: Throwable) -> Unit = {
            it.printStackTrace()
            action_networkError.postValue(true)
            toView(ACTION_HIDE_DIALOG)
        }
        mLastSearch = text
        request(onError) {
            //
            Repo.searchHistory.addNewSearch(text)
            refreshRecentItemList()
            //
            val searchResultList = arrayListOf<SearchBean>()
            val userSearch = Repo.http.userSearch(1, mPageSize, text)
            if (userSearch.isSuccess()) {
                val data: List<UserSearchBean> = userSearch.data!!
                data.forEach {
                    searchResultList.add(SearchBean(SearchBean.TYPE_SEARCH_RESULT_USER, user = it))
                }
            } else {
                Log.e(TAG, "result=" + userSearch.msg)
                userSearch.msg.let { sendHintMessage(it) }
            }

            val keywordSearch = Repo.http.keywordSearch(1, mPageSize, text)
            if (keywordSearch.isSuccess()) {
                mIndex = 2
                val data: List<IndexContentBean> = keywordSearch.data!!
                data.forEach {
                    searchResultList.add(SearchBean(SearchBean.TYPE_SEARCH_RESULT_CONTENT, content = it))
                }
                mSearchResultList.postValue(searchResultList)
                mEnableRefresh.postValue(false)
                if (data.size >= mPageSize) {
                    mEnableLoadMore.postValue(true)
                } else {
                    LoggerManager.d(
                            TAG,
                            "no more result, searchResultList.size=${searchResultList.size}"
                    )
                    mEnableLoadMore.postValue(false)
                }
            } else {
                Log.e(TAG, "result=" + keywordSearch.msg)
                keywordSearch.msg.let { sendHintMessage(it) }
            }
            toView(ACTION_HIDE_DIALOG)
        }
    }

    fun getMoreSearchData() {
        toView(ACTION_SHOW_DIALOG)
        val onError: (error: Throwable) -> Unit = {
            it.printStackTrace()
            action_networkError.postValue(true)
            toView(ACTION_HIDE_DIALOG)
        }
        request(onError) {
            val result = Repo.http.keywordSearch(mIndex, mPageSize, mLastSearch!!)
            if (result.isSuccess()) {
                mIndex++
                val data: List<IndexContentBean> = result.data!!
                //检测是否有更多数据
                if (data.size >= mPageSize) {
                    mEnableLoadMore.postValue(true)
                } else {
                    LoggerManager.d(TAG, "no more result, searchResultList.size=${data.size}")
                    mEnableLoadMore.postValue(false)
                }
                //
                if (data.size > 1) {
                    val value = mSearchResultList.value!!
                    val newArr = arrayListOf<SearchBean>()
                    for (i in value) {
                        newArr.add(i)
                    }
                    data.forEach {
                        newArr.add(SearchBean(SearchBean.TYPE_SEARCH_RESULT_CONTENT, content = it))
                    }
                    mSearchResultList.postValue(newArr)
                }
            } else {
                Log.e(TAG, "result=" + result.msg)
                result.msg.let { sendHintMessage(it) }
            }
            toView(ACTION_HIDE_DIALOG)
        }
    }

    fun subscription(data: UserSearchBean, position: Int){
        toView(ACTION_SHOW_DIALOG)
        val onError: (error: Throwable) -> Unit = {
            it.printStackTrace()
            sendHintMessage(com.sense.kukoo.common_i18n.R.string.search_no_net_toast)
            toView(ACTION_HIDE_DIALOG)
        }
        request(onError) {
            val subscription = Repo.http.subscription(data.id)
            if (subscription.isSuccess()) {
                data.isSub = if (data.isFollow()) 0 else 1
                action_refreshPosition.postValue(position)
            } else {
                Log.e(TAG, "result=" + subscription.msg)
                subscription.msg.let { sendHintMessage(it) }
            }
            toView(ACTION_HIDE_DIALOG)
        }
    }

}